﻿//								Source file
// Purpose: 
//=============================================================================
#include "Entity.h"
#include "App.h"
#include <freeglut.h>
// матрицы преобразования
static mat4 MVPm, viewMatrix,
            projectionMatrix, viewProjectionMatrix;
// индексы полученный из шейдерной программы
static GLint colorTextureLocation = -1, MVPmLocation = -1, ProgramLocation = -1;

float	_scale = 0.3;
GLuint	programCur = 0;

Shape *myModel;

cRenderDevice  *pRender        = NULL;
cShaderProgram *currentProgram = NULL;
cTexture       *pTexture;
cTimer         *pTimer;
GLuint	glslProgram = 0, handleTexture = 0;

bool init()	
{
	cwLogger::create("Log.txt");

	InitGLEW();
	InitDevIL();

	pRender = new cRenderDevice;

	// отсечения невидемых граней	
	glCullFace(GL_BACK);
	glFrontFace(GL_CCW);
	// полноэкранное сглаживание	
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_TEXTURE_2D);

	cTimer::init();
	cTimer::update();

	cFileManager::regiserPath("data/models/");
	cFileManager::regiserPath("data/shaders/");

	cImage *img = new cImage;
	img->loadImage( cFileManager::lookUpPath("signTex0.tga") );
	pTexture = new cTexture;
	pTexture->CreateTexture(img);
	delete img;

	std::string pathVert = cFileManager::lookUpPath("base.vert");
	std::string pathFrag = cFileManager::lookUpPath("base.frag");

	cProgramManager::createProgram(pathVert.c_str(),pathFrag.c_str(),"base");
	cProgramManager::at("base")->UseProgram();

    const float aspectRatio = 500 / 500;
    perspective( projectionMatrix, 90.0f, aspectRatio, 1.0f, 100.0f );

    viewMatrix = translation( 0, 0, -7 );

    viewProjectionMatrix = projectionMatrix * viewMatrix;
	
	colorTextureLocation = cProgramManager::at("base")->setUniform1i( "color2DTexture",0 );
    MVPmLocation = cProgramManager::at("base")->getLocationUniform( "MVPm" );
    
    return true;
}

void display()
{
	pTimer->update();

    glClearColor( 0.f, 0.f, 1.f, 1.f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	cProgramManager::at("base")->UseProgram();

    // передаем в текущую собранную шейдерную программу матрицу преобразования координат вершин
    cProgramManager::at("base")->setUniformMatrix4fv( MVPmLocation, MVPm.m_arr );


	myModel->draw();

    // рассчитываем MVPm (Model View Projection matrix)
	myModel->update();
	MVPm = viewProjectionMatrix * myModel->mtrModel * scale( _scale, _scale, _scale );

	glutSwapBuffers(); 
}

void reshape( int w, int h)
{
    glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
}

void keyfunc( unsigned char key, int x, int y )
{
    if( key == 27 || key == 'q' || key == 'Q' )	//	quit requested
        exit ( 0 );
    
    if( key == 'p')
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void mouseWheel( int wheel, int dir, int mouseX, int mouseY )
{
    if ( dir > 0 )
        _scale += 0.05;
    else
        _scale -= 0.05;

    glutPostRedisplay();
}

int main( int argc, char* argv[] )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    glutInitWindowSize( 500, 500 );

    glutInitContextVersion( 3,3 );
    glutInitContextFlags( GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG );
    glutInitContextProfile( GLUT_CORE_PROFILE ); // 3.3

    glutCreateWindow( "doLoadMesh" );

    glutDisplayFunc( display );
    glutReshapeFunc( reshape );
    glutKeyboardFunc( keyfunc );
    glutMouseWheelFunc( mouseWheel );

    init();

	myModel = new Shape;
    myModel->init( "OneSign.IFM",true );

    glutMainLoop();

    delete myModel;

	delete pRender;

    return 0;
}